/**
 * @author Rid King
 * @since 2017-04-29
 * @version 2.0.0
 * @description 缓冲器类
 */

class Retarder {
    /**
     * @function 构造方法
     * @param resolve <Function> // 方法函数
     * @param reject <Function> // 提醒函数
     * @param options <Object> // 操作方法
    */
    constructor (resolve, reject, options) {
        // 合并配置
        this.options = Object.assign({
            time: 500, // 延迟时长ms
        }, options || {})

        // 处理操作方法
        this.operate(resolve, reject)
    }

    /**
     * @function 添加操作方法
     * @param resolve <Function> // 方法函数
     * @param reject <Function> // 提醒函数
    */
    operate (resolve, reject) {
        // 操作方法处理
        resolve = typeof resolve === 'function' ? resolve : function () {}
        // 操作方法
        this._handler = function () {
            // 添加标志解析中
            this._resolving = true
            // 执行操作
            try {
                resolve.apply(this, arguments)
            }
            // 异常重置状态
            catch (e) {
                throw new Error(e)
                this.complete()
            }
        }

        // 提醒方法
        this._reject = reject

        return this
    }

    /**
     * @function 发射操作
     * @param data1 <any> // 数据1
     * [@param data2 <any> // 数据2]
    */
    emit () {
        // 参数处理
        let args = []
        for (let i  = 0; i < arguments.length; i++) {
            args.push(arguments[i])
        }
        // 添加缓冲器至参数中
        args.push(this)

        // 已经在发射中不执行操作，提示执行
        if (this._resolving) {
            typeof this._reject === 'function' && this._reject.apply(this, args)
            return this
        }

        // 如果已有计时器则取消
        this._timer && clearTimeout(this._timer)

        // 创建定时器
        this._timer = setTimeout(() => {
            // 执行中不继续执行
            if (this._resolving) {
                return false
            }
            // 执行
            this._handler.apply(this, args)
        }, this.options.time)

        return this
    }

    /**
     * @function 完成状态
    */
    complete () {
        // 改变执行状态
        this._resolving = false
        this._timer && clearTimeout(this._timer)

        return this
    }
}